from hashlib import md5

from django.contrib.auth.hashers import check_password, make_password
from django.contrib.auth.models import User
from django.http.response import JsonResponse, HttpResponseForbidden, HttpResponse
from django.shortcuts import render, redirect
from user.tasks import send_mail
from user.models import UserInfo
from django_redis import get_redis_connection
from user.models import UserScore, ScoreConfig
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from user.manages import UserScoreManager
from django.contrib.auth import login as auth_login, logout as auth_logout

from message.models import Swiper
from res.models import Resource


def register(request):
    """注册第一步"""

    if request.method == 'GET':
        return render(request, 'register.html')

    username = request.POST.get('username')
    password = request.POST.get('password')
    email = request.POST.get('email')

    # 校验手机号
    queryset = User.objects.filter(username=username)
    if queryset.exists():
        # 异步请求 返回json数据
        return JsonResponse(data={'code': 400, 'msg': '该手机号被注册'})

    # 校验邮箱
    queryset2 = User.objects.filter(email=email)
    if queryset2.exists():
        return JsonResponse(data={'code': 400, 'msg': '邮箱已经被绑定'})

    # 插入数据
    user = User.objects.create_user(username=username, password=password, email=email, is_active=False)
    # 生成 签名
    message = f"uid={user.pk}$site=www.lovedown.com"
    sign_text = md5(message.encode('utf-8')).hexdigest()
    return JsonResponse(data={'code': 200, 'msg': '注册成功', 'uid': user.pk, 'sign': sign_text})


def register2(request):
    """注册第二步"""
    if request.method == 'GET':
        uid = request.GET.get('uid')
        sign = request.GET.get('sign')
        # 校验签名
        message = f"uid={uid}$site=www.lovedown.com"
        sign_text = md5(message.encode('utf-8')).hexdigest()

        if sign_text != sign:
            return HttpResponseForbidden('禁止访问')
        # 校验成功 跳转
        return render(request, 'next_reg.html', context={'uid': uid})

    # 获取表单数据
    user_id = _post_parameter(request, 'uid')
    birthday = _post_parameter(request, 'birthday')
    nickname = _post_parameter(request, 'nickname', generator_nickname())
    name = _post_parameter(request, 'name')
    gender = _post_parameter(request, 'gender', "S")

    # 用户存在 就更新 不存在就创建
    if UserInfo.objects.filter(user_id=user_id).exists():
        # 日期不能为空
        UserInfo.objects.filter(user_id=user_id).update(birthday=birthday, nickname=nickname, name=name,
                                                        gender=gender)
    else:
        UserInfo.objects.create(user_id=user_id, birthday=birthday, nickname=nickname, name=name, gender=gender)

    # 邮件激活
    redis_client = get_redis_connection()
    redis_key = f"active:{user_id}"

    _send_email(request, user_id, redis_client, redis_key)

    return JsonResponse(data={'code': 200, 'msg': '基本信息保存成功', 'nickname': nickname})


def _send_email(request, user_id, redis_client, redis_key):
    # 邮件激活
    message = f"uid={user_id}$site=www.lovedown.com"
    sign_text = md5(message.encode('utf-8')).hexdigest()
    link_url = f"{request.scheme}://{request.get_host()}/active?uid={user_id}&sign={sign_text}"
    template = f"""
            <!DOCTYPE html>
<html>
<head>
    <style>
        body {{ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #2c3e50; margin: 0; padding: 0; }}
        .email-container {{ max-width: 600px; margin: 0 auto; background: white; border: 1px solid #e0e0e0; }}
        .header {{ background: #3498db; padding: 30px; text-align: center; }}
        .logo {{ color: white; font-size: 28px; font-weight: bold; }}
        .content {{ padding: 40px; }}
        .activation-box {{ background: #f8f9fa; border-left: 4px solid #3498db; padding: 20px; margin: 20px 0; }}
        .btn-primary {{ background: #3498db; color: white; padding: 14px 35px; text-decoration: none; border-radius: 4px; display: inline-block; }}
        .link-text {{ background: #ecf0f1; padding: 15px; border-radius: 4px; font-family: monospace; word-break: break-all; }}
        .footer {{ background: #34495e; color: #bdc3c7; padding: 20px; text-align: center; font-size: 12px; }}
    </style>
</head>
<body>
    <div class="email-container">
        <div class="header">
            <div class="logo">Lovedownload</div>
        </div>
        
        <div class="content">
            <h2>账号激活通知</h2>
            <p>尊敬的用户，您好！</p>
            <p>您已成功注册 Lovedownload 平台，只需完成最后一步激活操作即可开始使用：</p>
            
            <div class="activation-box">
                <p><strong>请点击下方按钮完成账号激活：</strong></p>
                <a href="{link_url}" class="btn-primary">确认激活账号</a>
            </div>
            
            <p>或者手动复制以下链接到浏览器：</p>
            <div class="link-text">{link_url}</div>
            
            <p><strong>安全提示：</strong></p>
            <ul>
                <li>此链接有效期1小时</li>
                <li>请勿将此链接分享给他人</li>
                <li>如非本人操作，请忽略此邮件</li>
            </ul>
        </div>
        
        <div class="footer">
            <p>© 2024 Lovedownload. 版权所有</p>
            <p>客户服务 | 隐私政策 | 使用条款</p>
        </div>
    </div>
</body>
</html>
            """
    try:
        user = User.objects.get(pk=user_id)
        send_mail.delay(subject='激活账号', body=template, to=user.email)
    except Exception as e:
        print("邮件发送失败")
    # 将 激活连接 存储到 redis 中，并设置过期时间 为 1 小时
    redis_client.setex(redis_key, 3600, sign_text)


def _post_parameter(request, key, default=None):
    """
    解决 register2 中的表单数据 校验 或者给默认值
    """
    val = request.POST.get(key)
    if not val:
        return default
    return val.strip()


# 生成一个随机昵称
def generator_nickname():
    import random
    return "love" + "".join(random.choices("0123456789", k=6))


def upload_avatar(request):
    """
    头像上传
    """
    avatar = request.FILES.get('avatar')
    uid = int(request.POST.get('uid'))

    # 如果 用户已经有头像
    if UserInfo.objects.filter(user_id=uid).exists():
        info = UserInfo.objects.get(user_id=uid)
        # 更新头像 tb_user_info 是avtar字段
        info.avtar = avatar
        info.save()
    else:
        info = UserInfo.objects.create(avtar=avatar, user_id=uid)

    return JsonResponse(data={'code': 200, 'msg': '上传成功'})


def success(request):
    """
    注册成功
    """
    # 添加 referer 头校验
    # 如果 不是从 register2 跳转过来的，禁止访问
    if not (referer := request.META.get('HTTP_REFERER', None)) or "/register2" not in referer:
        return HttpResponseForbidden('禁止访问')

    nickname = request.GET.get('nickname')

    return render(request, 'success.html',
                  context={"nickname": nickname})


def active(request):
    """
    激活账号
    """
    # 1 接收浏览器的参数
    user_id = request.GET.get('uid')
    sign_text = request.GET.get("sign")
    # 2 进行数字认证
    message = f"uid={user_id}$site=www.lovedown.com"

    if sign_text != md5(message.encode('utf-8')).hexdigest():
        return HttpResponseForbidden('认证失败')

    # 3验证 是否激活
    if User.objects.filter(pk=user_id, is_active=True).exists():
        return HttpResponse('账号已经激活，请勿重复激活')

    # 4 连接 redis 查看是否过期
    redis_client = get_redis_connection()
    redis_key = f"active:{user_id}"

    if not (val := redis_client.get(redis_key)) or val.decode('utf-8') != sign_text:
        return HttpResponseForbidden('激活链接已失效，请重新登录，系统会再次发送激活链接')

    # 5 认证成功 激活账号
    User.objects.filter(pk=user_id).update(is_active=True)
    # 删除 redis 中的 key
    redis_client.delete(redis_key)

    # 6 赠送积分
    # 查询积分数量

    # 自定义模型管理器
    UserScore.objects.create_score('注册', user_id=user_id, remark='用户注册')

    # 7 返回 激活成功页面
    redirect_url = f"{request.scheme}://{request.get_host()}/login"
    return HttpResponse(f"<h1>激活成功，点击进入 <a href={redirect_url} target='_blank'>登录</a> 页面</h1>")


def login(request):
    """密码登录"""
    if request.method == 'GET':
        next_url = request.GET.get('next', '/')
        print(next_url)
        return render(request, 'login.html', {'nextUrl': next_url})

    # 1 接收 账号，密码
    username = request.POST.get('username')
    password = request.POST.get('password')
    remember = request.POST.get('remember')  # str类型的true和 false

    # 2 根据用户名 查找用户是否存在
    queryset = User.objects.filter(username=username)
    # 如果没有注册，提示 用户名或密码 不正确
    if not queryset.exists():
        return JsonResponse(data={'code': 400, 'msg': '用户名或密码不正确'})
    user = queryset.first()
    # 判断是否激活 ，如果没有激活 查看 redis 是否过期
    if not user.is_active:

        redis_client = get_redis_connection()
        redis_key = f"active:{user.pk}"
        if not redis_client.get(redis_key):
            # 没有过期 提示 用户激活 过期啦 重新发送激活邮箱
            _send_email(request, user.pk, redis_client, redis_key)
        return JsonResponse(data={'code': 400, 'msg': '账号未激活，激活邮件已发送，请查看邮箱并激活'})

    # 比较密精密 是否一致
    if not check_password(password, user.password):
        return JsonResponse(data={'code': 400, 'msg': '用户名或密码不正确'})

    # 3 进行登录

    auth_login(request, user)

    # 如果没有 记住我 ，设置 session 为会话Cookie
    if remember == 'false':
        request.session.set_expiry(0)
    return JsonResponse(data={'code': 200, 'msg': '登录成功'})


def logout(request):
    """退出登录"""
    auth_logout(request)
    return redirect('login')


def send_login_code(request):
    """
    发送登录验证码
    """
    # 1 接收 邮箱
    email = request.POST.get('email')
    # 2 判断邮箱是否已经注册
    if not User.objects.filter(email=email).exists():
        return JsonResponse(data={'code': 400, 'msg': '邮箱未注册'})

    # 3 生成验证码
    import random
    code = "".join(random.choices("0123456789", k=6))

    # 4 保存到 redis 中 设置过期时间
    redis_client = get_redis_connection()
    redis_key = f"login:{email}"
    redis_client.set(redis_key, code, ex=60 * 5)

    # 5 发送邮件
    send_mail(subject='LoveDownload', body=f'登录验证码{code}', to=email)

    return JsonResponse(data={'code': 200, 'msg': '验证码已发送，请注意查收'})


def email_login(request):
    """
    邮箱登录
    """
    if request.method == 'GET':
        return render(request, 'login.html')

    # 1 接收 账号，密码
    email = request.POST.get('email')
    code = request.POST.get('code')
    remember = request.POST.get('remember')  # str类型的true和 false

    # 2 根据邮箱 查找邮箱是否 被绑定
    queryset = User.objects.filter(email=email)
    # 如果没有被绑定 提示 邮箱不存在
    if not queryset.exists():
        return JsonResponse(data={'code': 400, 'msg': '邮箱不存在'})
    user = queryset.first()

    # 判断是否激活 ，如果没有激活 查看 redis 是否过期
    redis_client = get_redis_connection()
    redis_key = f"login:{email}"

    if not user.is_active:

        if not redis_client.get(redis_key):
            # 没有过期 提示 用户激活 过期啦 重新发送激活邮箱
            _send_email(request, user.pk, redis_client, redis_key)
        return JsonResponse(data={'code': 400, 'msg': '账号未激活，激活邮件已发送，请查看邮箱并激活'})

    # 比较验证码是否 正确
    redis_code = redis_client.get(redis_key).decode('utf-8')
    if code != redis_code:
        return JsonResponse(data={'code': 400, 'msg': '验证码不正确'})

    # 删除 redis 中的 key
    redis_client.delete(redis_key)
    #  进行登录
    auth_login(request, user)

    # 如果没有 记住我 ，设置 session 为会话Cookie
    if remember == 'false':
        request.session.set_expiry(0)
    return JsonResponse(data={'code': 200, 'msg': '登录成功'})


def findpass(request):
    """找回密码"""
    if request.method == 'GET':
        return render(request, 'findpass.html')

    # 1 接收 账号，邮箱
    username = request.POST.get('username')
    email = request.POST.get('email')

    # 2 判断账号密码是否正确
    queryset = User.objects.filter(username=username, email=email)
    if not queryset.exists():
        return JsonResponse(data={'code': 400, 'msg': '用户名或邮箱不正确'})
    user = queryset.first()

    # 判断是否 已经有临时密码
    redis_client = get_redis_connection()
    redis_key = f"tem_password:{user.pk}"
    if redis_client.get(redis_key):
        return JsonResponse(data={'code': 200, 'msg': '临时密码已发送，请查看邮箱', 'id': user.pk})

    # 3 生成一个临时密码 发送到 用户的邮箱中
    import random
    password = "".join(random.choices("0123456789", k=6))
    user.set_password(password)
    user.save()

    # 临时密码 存储到redis中 并设置过期时间

    redis_client.set(redis_key, password, ex=60 * 5)

    # 4 发送邮件
    send_mail(subject='LoveDownload', body=f'临时密码{password}', to=email)
    return JsonResponse(data={'code': 200, 'msg': '临时密码已发送到邮件当中 请注意查收', 'id': user.pk})


def modifypass(request, pk):
    """修改密码"""
    # 添加 referer 头校验  如果 不是从 findpass 跳转过来的，禁止访问
    referer = request.META.get('HTTP_REFERER', None)
    if referer is None or ("/findpass" not in referer) and ("/modifypass" not in referer):
        return HttpResponseForbidden('禁止访问')

    if request.method == 'GET':
        return render(request, 'modifypass.html')

    # 1 接收 临时密码，新密码
    tem_password = request.POST.get('tem_password')
    password = request.POST.get('password')
    user_id = pk
    # 2 判断临时密码是否正确
    user = User.objects.filter(pk=user_id).first()

    if not user or not check_password(tem_password, user.password):
        return JsonResponse(data={'code': 400, 'msg': '临时密码不正确'})

    # 判断 redis中的 密码 是否过期
    redis_client = get_redis_connection()
    redis_key = f"tem_password:{user_id}"

    if not redis_client.get(redis_key):
        return JsonResponse(data={'code': 400, 'msg': '临时密码已过期,请重新获取'})

    # 3 修改密码
    user.set_password(password)
    user.save()

    # 4 删除 redis 中的 key
    redis_client.delete(redis_key)

    return JsonResponse(data={'code': 200, 'msg': '密码修改成功'})


def index(request):
    """首页
    资源和轮播图展示
    """

    images = Swiper.objects.filter(is_enable=True, type='0', is_delete=False)
    ad = Swiper.objects.filter(is_enable=True, type='1', is_delete=False).first()
    # 查询 所有精选 资源
    best_res = Resource.objects.filter(is_delete=False, is_best=True)
    for res in best_res:
        res.size = round(res.size / 1024, 1)  # 转换为 KB

        return render(request, 'index.html', context={'images': images, 'ad': ad, 'best_res': best_res})
